﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using SharpMap.Presentation.Wpf;
using SharpMap.Layers;
using System.Diagnostics;
using SharpMap.Styles;
using IO = System.IO;
using System.Reflection;
using SharpMap.Wpf.Converters;
namespace SharpMap.Wpf 
{

    public class MapLayer : ItemsControl
    {
        static readonly IValueConverter _strignToLayerConverter = new SharpMap.Wpf.Converters.StringLayerSourceConverter();
        public IStyle LayerStyle
        {
            get { return (IStyle)GetValue(LayerStyleProperty); }
            set { SetValue(LayerStyleProperty, value); }
        }
        public static readonly DependencyProperty LayerStyleProperty =
            DependencyProperty.Register("LayerStyle", typeof(IStyle),
            typeof(MapLayer),
            new FrameworkPropertyMetadata(default(IStyle), LayerStylePropertyChanged));

        public static readonly RoutedEvent LayerChangedEvent =
            EventManager.RegisterRoutedEvent("LayerChanged", RoutingStrategy.Bubble
                                            , typeof(RoutedEventHandler), typeof(MapLayer));




        public string WorldXPropertyPath
        {
            get { return (string)GetValue(WorldXPropertyPathProperty); }
            set { SetValue(WorldXPropertyPathProperty, value); }
        }
        public static readonly DependencyProperty WorldXPropertyPathProperty =
            DependencyProperty.Register("WorldXPropertyPath", typeof(string), typeof(MapLayer), new UIPropertyMetadata(default(string)));



        public string WorldYPropertyPath
        {
            get { return (string)GetValue(WorldYPropertyPathProperty); }
            set { SetValue(WorldYPropertyPathProperty, value); }
        }
        public static readonly DependencyProperty WorldYPropertyPathProperty =
            DependencyProperty.Register("WorldYPropertyPath", typeof(string), typeof(MapLayer), new UIPropertyMetadata(default(string)));




        static void LayerStylePropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            MapLayer This = target as MapLayer;
        }

        private void WireUp()
        {
            Binding b = new Binding("Style");
            
            //TODO: this is not the way to go. but for now...
            b.Mode = BindingMode.OneWayToSource;

            //b.Mode = BindingMode.TwoWay;


            b.Converter = new DummyConverter();
            SetBinding(LayerStyleProperty, b);
        }

        public event RoutedEventHandler LayerChanged
        {
            add 
            {
                AddHandler(LayerChangedEvent, value);
            }
            remove
            {
                RemoveHandler(LayerChangedEvent, value);
            }
        }

        public string Source
        {
            get { return (string)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(string), typeof(MapLayer),
            new UIPropertyMetadata(default(string), SourcePropertyChanged));

        static void SourcePropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            MapLayer This = target as MapLayer;
            if (This != null)
            {
                This.handleSourceChanged(e);
            }
        }

        private void handleSourceChanged(DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue is string)
            {
                CleanUpCurentContent();
                ILayer layer = LoadLayerFromFile(e.NewValue as string) as ILayer;
                
                if (LayerStyle != null)
                {
                    layer.Style = LayerStyle;
                }
                if (layer != null)
                {
                    ViewModel = new MapLayerViewModel(layer, this);
                    if (LayerStyle != null)
                    {
                        layer.Style = LayerStyle;
                    }
                    this.DataContext = ViewModel;
                    RaiseEvent(new RoutedEventArgs(LayerChangedEvent));
                }
            }
        }

        private object LoadLayerFromFile(string fileName)
        {
            string fullFileName;
            if (IO.Path.IsPathRooted(fileName))
            {
                fullFileName = fileName;
            }
            else
            {
                Assembly entryAssembly = Assembly.GetEntryAssembly();
                string exeDir = IO.Path.GetDirectoryName(entryAssembly.Location);
                fullFileName = IO.Path.Combine(exeDir, fileName);
            }

            SharpMap.Data.Providers.ShapeFile.ShapeFileProvider shapFile =
                    new SharpMap.Data.Providers.ShapeFile.ShapeFileProvider(fullFileName);
            String layerName = IO.Path.GetFileNameWithoutExtension(fileName);

            SharpMap.Layers.GeometryLayer layer = new SharpMap.Layers.GeometryLayer(layerName, shapFile);
            return layer;
        }

        private void CleanUpCurentContent()
        {
            //TODO: implement
        }

        static MapLayer()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MapLayer), new FrameworkPropertyMetadata(typeof(MapLayer)));
            DataContextProperty.OverrideMetadata(
                typeof(MapLayer), new FrameworkPropertyMetadata(DataContextPropertyChanged));

        }

        static void DataContextPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            MapLayer This = target as MapLayer;
        }

        public MapLayer()
        {
            WireUp();
        }

        internal void PrapareMapLayer(object item)
        {
            if (Layer != null)
            {
                if (!Layer.DataSource.IsOpen)
                {
                    Layer.DataSource.Open();
                }
            }
        }


        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            base.PrepareContainerForItemOverride(element, item);
            //TODO: should be binding actually
            if ( (!double.IsNaN((GeoPanel.GetWorldX(element)))  && !(double.IsNaN(GeoPanel.GetWorldY(element) )) )
                || (string.IsNullOrEmpty(WorldXPropertyPath) || (string.IsNullOrEmpty(WorldYPropertyPath))))
            {
                return;
            }
            Binding xb = new Binding(WorldXPropertyPath);
            xb.Source = item;
            BindingOperations.SetBinding(element, GeoPanel.WorldXProperty, xb);

            Binding yb = new Binding(WorldYPropertyPath);
            yb.Source = item;
            BindingOperations.SetBinding(element, GeoPanel.WorldYProperty, yb);
    

            
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is FrameworkElement;
        }



        internal MapLayerViewModel ViewModel
        {
            get { return _viewModel; }
            set { _viewModel = value; }
        }
         internal ILayer Layer
        {
            get { return ViewModel != null ? ViewModel.Layer : null;}
        }
        MapLayerViewModel _viewModel;
    }
}
